home *** CD-ROM | disk | FTP | other *** search
/ Enter 2006 September / Enter 09 2006.iso / Internet / SpamExperts Home 1.1 / SpamExperts Home.exe / lib / spamexperts.modules / PngImagePlugin.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2006-07-14  |  13.9 KB  |  454 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. __version__ = '0.8.2'
  5. import re
  6. import string
  7. import Image
  8. import ImageFile
  9. import ImagePalette
  10.  
  11. def i16(c):
  12.     return ord(c[1]) + (ord(c[0]) << 8)
  13.  
  14.  
  15. def i32(c):
  16.     return ord(c[3]) + (ord(c[2]) << 8) + (ord(c[1]) << 16) + (ord(c[0]) << 24)
  17.  
  18. is_cid = re.compile('\\w\\w\\w\\w').match
  19. _MAGIC = '\x89PNG\r\n\x1a\n'
  20. _MODES = {
  21.     (1, 0): ('1', '1'),
  22.     (2, 0): ('L', 'L;2'),
  23.     (4, 0): ('L', 'L;4'),
  24.     (8, 0): ('L', 'L'),
  25.     (16, 0): ('I', 'I;16B'),
  26.     (8, 2): ('RGB', 'RGB'),
  27.     (16, 2): ('RGB', 'RGB;16B'),
  28.     (1, 3): ('P', 'P;1'),
  29.     (2, 3): ('P', 'P;2'),
  30.     (4, 3): ('P', 'P;4'),
  31.     (8, 3): ('P', 'P'),
  32.     (8, 4): ('LA', 'LA'),
  33.     (16, 4): ('RGBA', 'LA;16B'),
  34.     (8, 6): ('RGBA', 'RGBA'),
  35.     (16, 6): ('RGBA', 'RGBA;16B') }
  36.  
  37. class ChunkStream:
  38.     
  39.     def __init__(self, fp):
  40.         self.fp = fp
  41.         self.queue = []
  42.         if not hasattr(Image.core, 'crc32'):
  43.             self.crc = self.crc_skip
  44.         
  45.  
  46.     
  47.     def read(self):
  48.         '''Fetch a new chunk. Returns header information.'''
  49.         if self.queue:
  50.             (cid, pos, len) = self.queue[-1]
  51.             del self.queue[-1]
  52.             self.fp.seek(pos)
  53.         else:
  54.             s = self.fp.read(8)
  55.             cid = s[4:]
  56.             pos = self.fp.tell()
  57.             len = i32(s)
  58.         if not is_cid(cid):
  59.             raise SyntaxError, 'broken PNG file (chunk %s)' % repr(cid)
  60.         
  61.         return (cid, pos, len)
  62.  
  63.     
  64.     def close(self):
  65.         self.queue = None
  66.         self.crc = None
  67.         self.fp = None
  68.  
  69.     
  70.     def push(self, cid, pos, len):
  71.         self.queue.append((cid, pos, len))
  72.  
  73.     
  74.     def call(self, cid, pos, len):
  75.         '''Call the appropriate chunk handler'''
  76.         if Image.DEBUG:
  77.             print 'STREAM', cid, pos, len
  78.         
  79.         return getattr(self, 'chunk_' + cid)(pos, len)
  80.  
  81.     
  82.     def crc(self, cid, data):
  83.         '''Read and verify checksum'''
  84.         crc1 = Image.core.crc32(data, Image.core.crc32(cid))
  85.         crc2 = (i16(self.fp.read(2)), i16(self.fp.read(2)))
  86.         if crc1 != crc2:
  87.             raise SyntaxError, 'broken PNG file(bad header checksum in %s)' % cid
  88.         
  89.  
  90.     
  91.     def crc_skip(self, cid, data):
  92.         '''Read checksum.  Used if the C module is not present'''
  93.         self.fp.read(4)
  94.  
  95.     
  96.     def verify(self, endchunk = 'IEND'):
  97.         cids = []
  98.         while None:
  99.             (cid, pos, len) = self.read()
  100.             if cid == endchunk:
  101.                 break
  102.             
  103.             cids.append(cid)
  104.         return cids
  105.  
  106.  
  107.  
  108. class PngInfo:
  109.     
  110.     def __init__(self):
  111.         self.chunks = []
  112.  
  113.     
  114.     def add(self, cid, data):
  115.         self.chunks.append((cid, data))
  116.  
  117.     
  118.     def add_text(self, key, value, zip = 0):
  119.         if zip:
  120.             import zlib
  121.             self.add('zTXt', key + '\x00\x00' + zlib.compress(value))
  122.         else:
  123.             self.add('tEXt', key + '\x00' + value)
  124.  
  125.  
  126.  
  127. class PngStream(ChunkStream):
  128.     
  129.     def __init__(self, fp):
  130.         ChunkStream.__init__(self, fp)
  131.         self.im_info = { }
  132.         self.im_size = (0, 0)
  133.         self.im_mode = None
  134.         self.im_tile = None
  135.         self.im_palette = None
  136.  
  137.     
  138.     def chunk_IHDR(self, pos, len):
  139.         s = ImageFile._safe_read(self.fp, len)
  140.         self.im_size = (i32(s), i32(s[4:]))
  141.         
  142.         try:
  143.             (self.im_mode, self.im_rawmode) = _MODES[(ord(s[8]), ord(s[9]))]
  144.         except:
  145.             pass
  146.  
  147.         if ord(s[12]):
  148.             self.im_info['interlace'] = 1
  149.         
  150.         if ord(s[11]):
  151.             raise SyntaxError, 'unknown filter category'
  152.         
  153.         return s
  154.  
  155.     
  156.     def chunk_IDAT(self, pos, len):
  157.         self.im_tile = [
  158.             ('zip', (0, 0) + self.im_size, pos, self.im_rawmode)]
  159.         self.im_idat = len
  160.         raise EOFError
  161.  
  162.     
  163.     def chunk_IEND(self, pos, len):
  164.         raise EOFError
  165.  
  166.     
  167.     def chunk_PLTE(self, pos, len):
  168.         s = ImageFile._safe_read(self.fp, len)
  169.         if self.im_mode == 'P':
  170.             self.im_palette = ('RGB', s)
  171.         
  172.         return s
  173.  
  174.     
  175.     def chunk_tRNS(self, pos, len):
  176.         s = ImageFile._safe_read(self.fp, len)
  177.         if self.im_mode == 'P':
  178.             i = string.find(s, chr(0))
  179.             if i >= 0:
  180.                 self.im_info['transparency'] = i
  181.             
  182.         elif self.im_mode == 'L':
  183.             self.im_info['transparency'] = i16(s)
  184.         
  185.         return s
  186.  
  187.     
  188.     def chunk_gAMA(self, pos, len):
  189.         s = ImageFile._safe_read(self.fp, len)
  190.         self.im_info['gamma'] = i32(s) / 100000.0
  191.         return s
  192.  
  193.     
  194.     def chunk_pHYs(self, pos, len):
  195.         s = ImageFile._safe_read(self.fp, len)
  196.         px = i32(s)
  197.         py = i32(s[4:])
  198.         unit = ord(s[8])
  199.         if unit == 1:
  200.             dpi = (int(px * 0.025399999999999999 + 0.5), int(py * 0.025399999999999999 + 0.5))
  201.             self.im_info['dpi'] = dpi
  202.         elif unit == 0:
  203.             self.im_info['aspect'] = (px, py)
  204.         
  205.         return s
  206.  
  207.     
  208.     def chunk_tEXt(self, pos, len):
  209.         s = ImageFile._safe_read(self.fp, len)
  210.         
  211.         try:
  212.             (k, v) = string.split(s, '\x00', 1)
  213.         except ValueError:
  214.             k = s
  215.             v = ''
  216.  
  217.         if k:
  218.             self.im_info[k] = v
  219.         
  220.         return s
  221.  
  222.  
  223.  
  224. def _accept(prefix):
  225.     return prefix[:8] == _MAGIC
  226.  
  227.  
  228. class PngImageFile(ImageFile.ImageFile):
  229.     format = 'PNG'
  230.     format_description = 'Portable network graphics'
  231.     
  232.     def _open(self):
  233.         if self.fp.read(8) != _MAGIC:
  234.             raise SyntaxError, 'not a PNG file'
  235.         
  236.         self.png = PngStream(self.fp)
  237.         while None:
  238.             (cid, pos, len) = self.png.read()
  239.             
  240.             try:
  241.                 s = self.png.call(cid, pos, len)
  242.             except EOFError:
  243.                 break
  244.             except AttributeError:
  245.                 if Image.DEBUG:
  246.                     print cid, pos, len, '(unknown)'
  247.                 
  248.                 s = ImageFile._safe_read(self.fp, len)
  249.  
  250.         self.mode = self.png.im_mode
  251.         self.size = self.png.im_size
  252.         self.info = self.png.im_info
  253.         self.tile = self.png.im_tile
  254.         if self.png.im_palette:
  255.             (rawmode, data) = self.png.im_palette
  256.             self.palette = ImagePalette.raw(rawmode, data)
  257.         
  258.         self._PngImageFile__idat = len
  259.  
  260.     
  261.     def verify(self):
  262.         '''Verify PNG file'''
  263.         if self.fp is None:
  264.             raise RuntimeError('verify must be called directly after open')
  265.         
  266.         self.fp.seek(self.tile[0][2] - 8)
  267.         self.png.verify()
  268.         self.png.close()
  269.         self.fp = None
  270.  
  271.     
  272.     def load_prepare(self):
  273.         '''internal: prepare to read PNG file'''
  274.         if self.info.get('interlace'):
  275.             raise IOError('cannot read interlaced PNG files')
  276.         
  277.         ImageFile.ImageFile.load_prepare(self)
  278.  
  279.     
  280.     def load_read(self, bytes):
  281.         '''internal: read more image data'''
  282.         while self._PngImageFile__idat == 0:
  283.             self.fp.read(4)
  284.             (cid, pos, len) = self.png.read()
  285.             if cid not in [
  286.                 'IDAT',
  287.                 'DDAT']:
  288.                 self.png.push(cid, pos, len)
  289.                 return ''
  290.             
  291.             self._PngImageFile__idat = len
  292.         if bytes <= 0:
  293.             bytes = self._PngImageFile__idat
  294.         else:
  295.             bytes = min(bytes, self._PngImageFile__idat)
  296.         self._PngImageFile__idat = self._PngImageFile__idat - bytes
  297.         return self.fp.read(bytes)
  298.  
  299.     
  300.     def load_end(self):
  301.         '''internal: finished reading image data'''
  302.         self.png.close()
  303.         self.png = None
  304.  
  305.  
  306.  
  307. def o16(i):
  308.     return chr(i >> 8 & 255) + chr(i & 255)
  309.  
  310.  
  311. def o32(i):
  312.     return chr(i >> 24 & 255) + chr(i >> 16 & 255) + chr(i >> 8 & 255) + chr(i & 255)
  313.  
  314. _OUTMODES = {
  315.     '1': ('1', chr(1) + chr(0)),
  316.     'L;1': ('L;1', chr(1) + chr(0)),
  317.     'L;2': ('L;2', chr(2) + chr(0)),
  318.     'L;4': ('L;4', chr(4) + chr(0)),
  319.     'L': ('L', chr(8) + chr(0)),
  320.     'LA': ('LA', chr(8) + chr(4)),
  321.     'I': ('I;16B', chr(16) + chr(0)),
  322.     'P;1': ('P;1', chr(1) + chr(3)),
  323.     'P;2': ('P;2', chr(2) + chr(3)),
  324.     'P;4': ('P;4', chr(4) + chr(3)),
  325.     'P': ('P', chr(8) + chr(3)),
  326.     'RGB': ('RGB', chr(8) + chr(2)),
  327.     'RGBA': ('RGBA', chr(8) + chr(6)) }
  328.  
  329. def putchunk(fp, cid, *data):
  330.     '''Write a PNG chunk (including CRC field)'''
  331.     data = string.join(data, '')
  332.     fp.write(o32(len(data)) + cid)
  333.     fp.write(data)
  334.     (hi, lo) = Image.core.crc32(data, Image.core.crc32(cid))
  335.     fp.write(o16(hi) + o16(lo))
  336.  
  337.  
  338. class _idat:
  339.     
  340.     def __init__(self, fp, chunk):
  341.         self.fp = fp
  342.         self.chunk = chunk
  343.  
  344.     
  345.     def write(self, data):
  346.         self.chunk(self.fp, 'IDAT', data)
  347.  
  348.  
  349.  
  350. def _save(im, fp, filename, chunk = putchunk, check = 0):
  351.     mode = im.mode
  352.     if mode == 'P':
  353.         if im.encoderinfo.has_key('bits'):
  354.             n = 1 << im.encoderinfo['bits']
  355.         else:
  356.             n = 256
  357.         if n <= 2:
  358.             bits = 1
  359.         elif n <= 4:
  360.             bits = 2
  361.         elif n <= 16:
  362.             bits = 4
  363.         else:
  364.             bits = 8
  365.         if bits != 8:
  366.             mode = '%s;%d' % (mode, bits)
  367.         
  368.     
  369.     if im.encoderinfo.has_key('dictionary'):
  370.         dictionary = im.encoderinfo['dictionary']
  371.     else:
  372.         dictionary = ''
  373.     im.encoderconfig = (im.encoderinfo.has_key('optimize'), dictionary)
  374.     
  375.     try:
  376.         (rawmode, mode) = _OUTMODES[mode]
  377.     except KeyError:
  378.         raise IOError, 'cannot write mode %s as PNG' % mode
  379.  
  380.     if check:
  381.         return check
  382.     
  383.     fp.write(_MAGIC)
  384.     chunk(fp, 'IHDR', o32(im.size[0]), o32(im.size[1]), mode, chr(0), chr(0), chr(0))
  385.     if im.mode == 'P':
  386.         chunk(fp, 'PLTE', im.im.getpalette('RGB'))
  387.     
  388.     if im.encoderinfo.has_key('transparency'):
  389.         if im.mode == 'P':
  390.             transparency = max(0, min(255, im.encoderinfo['transparency']))
  391.             chunk(fp, 'tRNS', chr(255) * transparency + chr(0))
  392.         elif im.mode == 'L':
  393.             transparency = max(0, min(65535, im.encoderinfo['transparency']))
  394.             chunk(fp, 'tRNS', o16(transparency))
  395.         else:
  396.             raise IOError, 'cannot use transparency for this mode'
  397.     
  398.     dpi = im.encoderinfo.get('dpi')
  399.     if dpi:
  400.         chunk(fp, 'pHYs', o32(int(dpi[0] / 0.025399999999999999 + 0.5)), o32(int(dpi[1] / 0.025399999999999999 + 0.5)), chr(1))
  401.     
  402.     info = im.encoderinfo.get('pnginfo')
  403.     if info:
  404.         for cid, data in info.chunks:
  405.             chunk(fp, cid, data)
  406.         
  407.     
  408.     ImageFile._save(im, _idat(fp, chunk), [
  409.         ('zip', (0, 0) + im.size, 0, rawmode)])
  410.     chunk(fp, 'IEND', '')
  411.     
  412.     try:
  413.         fp.flush()
  414.     except:
  415.         pass
  416.  
  417.  
  418.  
  419. def getchunks(im, **params):
  420.     '''Return a list of PNG chunks representing this image.'''
  421.     
  422.     class collector:
  423.         data = []
  424.         
  425.         def write(self, data):
  426.             pass
  427.  
  428.         
  429.         def append(self, chunk):
  430.             self.data.append(chunk)
  431.  
  432.  
  433.     
  434.     def append(fp, cid, *data):
  435.         data = string.join(data, '')
  436.         (hi, lo) = Image.core.crc32(data, Image.core.crc32(cid))
  437.         crc = o16(hi) + o16(lo)
  438.         fp.append((cid, data, crc))
  439.  
  440.     fp = collector()
  441.     
  442.     try:
  443.         im.encoderinfo = params
  444.         _save(im, fp, None, append)
  445.     finally:
  446.         del im.encoderinfo
  447.  
  448.     return fp.data
  449.  
  450. Image.register_open('PNG', PngImageFile, _accept)
  451. Image.register_save('PNG', _save)
  452. Image.register_extension('PNG', '.png')
  453. Image.register_mime('PNG', 'image/png')
  454.